#include "networkmanager.h"
#include <QNetworkRequest>
#include <QJsonParseError>
#include "configmanager.h"

NetworkManager::NetworkManager(QObject *parent)
    : QObject(parent)
    , networkAccessManager(new QNetworkAccessManager(this))
    , domain("http://"
        + ConfigManager::instance().getConfig().value("server_ip").toString() + ":"
             + QString::number(ConfigManager::instance().getConfig().value("server_port").toInt()))
{}

QNetworkReply* NetworkManager::sendRequest(RequestType type, const QString& name, const QJsonObject& json)
{
    QUrl url(domain + name);
    QNetworkRequest request(url);
    request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");

    if (type == RequestType::GET)
        return networkAccessManager->get(request);
    else if (type == RequestType::POST)
        return networkAccessManager->post(request, QJsonDocument(json).toJson());
    else
        throw std::runtime_error("Unknown Request Type!");
}

QJsonDocument NetworkManager::recvResponse(QNetworkReply *reply)
{
    if (!reply) return QJsonDocument();

    if (reply->error() != QNetworkReply::NoError) {
        qWarning() << "Network error:" << reply->errorString();
        return QJsonDocument();
    }

    QByteArray responseData = reply->readAll();
    QJsonDocument jsonDoc = QJsonDocument::fromJson(responseData);

    if (!jsonDoc.isObject()) {
        qWarning() << "Invalid JSON format in response";
        return QJsonDocument();
    }

    return jsonDoc;
}

// Request Interface Implementations

void NetworkManager::checkExpiry() {
    QNetworkReply *reply = sendRequest(RequestType::GET, "/checkExpiry");
    connect(reply, &QNetworkReply::finished, this, &NetworkManager::onCheckExpiryReplyFinished);
}

void NetworkManager::checkStock() {
    QNetworkReply *reply = sendRequest(RequestType::GET, "/checkStockAlerts");
    connect(reply, &QNetworkReply::finished, this, &NetworkManager::onCheckStockReplyFinished);
}

void NetworkManager::loginUser(const QJsonObject &json) {
    QNetworkReply *reply = sendRequest(RequestType::POST, "/loginUser", json);
    connect(reply, &QNetworkReply::finished, this, &NetworkManager::onLoginReplyFinished);
}

void NetworkManager::registerUser(const QJsonObject &json) {
    QNetworkReply *reply = sendRequest(RequestType::POST, "/registerUser", json);
    connect(reply, &QNetworkReply::finished, this, &NetworkManager::onRegisterReplyFinished);
}

void NetworkManager::deleteUser(const QJsonObject &json) {
    QNetworkReply *reply = sendRequest(RequestType::POST, "/deleteUser", json);
    connect(reply, &QNetworkReply::finished, this, &NetworkManager::onDeleteUserReplyFinished);
}

void NetworkManager::updateUser(const QJsonObject &json) {
    QNetworkReply *reply = sendRequest(RequestType::POST, "/updateUser", json);
    connect(reply, &QNetworkReply::finished, this, &NetworkManager::onUpdateUserReplyFinished);
}

void NetworkManager::addMedicine(const QJsonObject &json) {
    QNetworkReply *reply = sendRequest(RequestType::POST, "/addMedicine", json);
    connect(reply, &QNetworkReply::finished, this, &NetworkManager::onAddMedicineReplyFinished);
}

void NetworkManager::deleteMedicine(const QJsonObject &json) {
    QNetworkReply *reply = sendRequest(RequestType::POST, "/deleteMedicine", json);
    connect(reply, &QNetworkReply::finished, this, &NetworkManager::onDeleteMedicineReplyFinished);
}

void NetworkManager::editMedicine(const QJsonObject &json) {
    QNetworkReply *reply = sendRequest(RequestType::POST, "/editMedicine", json);
    connect(reply, &QNetworkReply::finished, this, &NetworkManager::onEditMedicineReplyFinished);
}

void NetworkManager::queryMedicineByName(const QJsonObject &json) {
    QNetworkReply *reply = sendRequest(RequestType::POST, "/queryMedicineByName", json);
    connect(reply, &QNetworkReply::finished, this, &NetworkManager::onQueryMedicineByNameReplyFinished);
}
void NetworkManager::queryMedicineByCategory(const QJsonObject &json) {
    QNetworkReply *reply = sendRequest(RequestType::POST, "/queryMedicineByCategory", json);
    connect(reply, &QNetworkReply::finished, this, &NetworkManager::onQueryMedicineByCategoryReplyFinished);
}
void NetworkManager::queryMedicineByKeyword(const QJsonObject &json) {
    QNetworkReply *reply = sendRequest(RequestType::POST, "/queryMedicineByKeyword", json);
    connect(reply, &QNetworkReply::finished, this, &NetworkManager::onQueryMedicineByKeywordReplyFinished);
}

void NetworkManager::createPurchaseOrder(const QJsonObject &json) {
    QNetworkReply *reply = sendRequest(RequestType::POST, "/createPurchaseOrder", json);
    connect(reply, &QNetworkReply::finished, this, &NetworkManager::onCreatePurchaseOrderReplyFinished);
}

void NetworkManager::queryPurchaseRecord(const QJsonObject &json)
{
    QNetworkReply *reply = sendRequest(RequestType::POST, "/queryPurchaseRecords", json);
    connect(reply, &QNetworkReply::finished, this, &NetworkManager::onQueryPurchaseRecordReplyFinished);
}

void NetworkManager::querySalesRecords(const QJsonObject &json) {
    QNetworkReply *reply = sendRequest(RequestType::POST, "/querySalesRecords", json);
    connect(reply, &QNetworkReply::finished, this, &NetworkManager::onQuerySalesRecordsReplyFinished);
}

void NetworkManager::takeMedicine(const QJsonObject &json) {
    QNetworkReply *reply = sendRequest(RequestType::POST, "/takeMedicine", json);
    connect(reply, &QNetworkReply::finished, this, &NetworkManager::onTakeMedicineReplyFinished);
}

// Response Slots Implementations

void NetworkManager::onCheckExpiryReplyFinished() {
    QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender());
    QJsonDocument jsonDoc = recvResponse(reply);
    emit checkExpiryResponseReceived(jsonDoc.object());
    reply->deleteLater();
}

void NetworkManager::onLoginReplyFinished() {
    QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender());
    QJsonDocument jsonDoc = recvResponse(reply);
    emit loginResponseReceived(jsonDoc.object());
    reply->deleteLater();
}

void NetworkManager::onRegisterReplyFinished() {
    QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender());
    QJsonDocument jsonDoc = recvResponse(reply);
    emit registerResponseReceived(jsonDoc.object());
    reply->deleteLater();
}

void NetworkManager::onDeleteUserReplyFinished() {
    QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender());
    QJsonDocument jsonDoc = recvResponse(reply);
    emit deleteUserResponseReceived(jsonDoc.object());
    reply->deleteLater();
}

void NetworkManager::onUpdateUserReplyFinished() {
    QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender());
    QJsonDocument jsonDoc = recvResponse(reply);
    emit updateUserResponseReceived(jsonDoc.object());
    reply->deleteLater();
}

void NetworkManager::onAddMedicineReplyFinished() {
    QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender());
    QJsonDocument jsonDoc = recvResponse(reply);
    emit addMedicineResponseReceived(jsonDoc.object());
    reply->deleteLater();
}

void NetworkManager::onDeleteMedicineReplyFinished() {
    QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender());
    QJsonDocument jsonDoc = recvResponse(reply);
    emit deleteMedicineResponseReceived(jsonDoc.object());
    reply->deleteLater();
}

void NetworkManager::onEditMedicineReplyFinished() {
    QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender());
    QJsonDocument jsonDoc = recvResponse(reply);
    emit editMedicineResponseReceived(jsonDoc.object());
    reply->deleteLater();
}

void NetworkManager::onQueryMedicineByNameReplyFinished() {
    QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender());
    QJsonDocument jsonDoc = recvResponse(reply);
    emit queryMedicineByNameResponseReceived(jsonDoc.object());
    reply->deleteLater();
}

void NetworkManager::onQueryMedicineByCategoryReplyFinished() {
    QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender());
    QJsonDocument jsonDoc = recvResponse(reply);
    emit queryMedicineByCategoryResponseReceived(jsonDoc.object());
    reply->deleteLater();
}

void NetworkManager::onQueryMedicineByKeywordReplyFinished() {
    QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender());
    QJsonDocument jsonDoc = recvResponse(reply);
    emit queryMedicineByKeywordResponseReceived(jsonDoc.object());
    reply->deleteLater();
}

void NetworkManager::onCheckStockReplyFinished() {
    QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender());
    QJsonDocument jsonDoc = recvResponse(reply);
    emit checkStockResponseReceived(jsonDoc.object());
    reply->deleteLater();
}

void NetworkManager::onCreatePurchaseOrderReplyFinished() {
    QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender());
    QJsonDocument jsonDoc = recvResponse(reply);
    emit createPurchaseOrderResponseReceived(jsonDoc.object());
    reply->deleteLater();
}

void NetworkManager::onQuerySalesRecordsReplyFinished() {
    QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender());
    QJsonDocument jsonDoc = recvResponse(reply);
    emit querySalesRecordsResponseReceived(jsonDoc.object());
    reply->deleteLater();
}

void NetworkManager::onQueryPurchaseRecordReplyFinished()
{
    QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender());
    QJsonDocument jsonDoc = recvResponse(reply);
    emit queryPurchaseRecordResponseReceived(jsonDoc.object());
    reply->deleteLater();
}

void NetworkManager::onTakeMedicineReplyFinished() {
    QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender());
    QJsonDocument jsonDoc = recvResponse(reply);
    emit takeMedicineResponseReceived(jsonDoc.object());
    reply->deleteLater();
}
